package gsw.demo.pluggable.plugin_simple;


import android.app.Application;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;

import java.lang.reflect.Method;

/**
 * 插件化简化版框
 * 注意：该框架只适用于API25以下
 */
public class PluginManagerSimple {
    private static PluginManagerSimple pluginManager;
    private Context context;
    private AssetManager assetManager;
    private Resources newResource;

    private PluginManagerSimple() {
    }

    public static PluginManagerSimple getInstance() {
        if (pluginManager == null) {
            synchronized (PluginManagerSimple.class) {
                if (pluginManager == null) {
                    pluginManager = new PluginManagerSimple();
                }
            }
        }
        return pluginManager;
    }

    /**
     * 初始化框架
     * 可以在Application.onCreate()或Activity.onCreate()中调用
     */
    public void init(Context context) {
        this.context = context;
        initPluginSimple();
        setAssetManager();
        setResources();
    }

    /**
     * 初始化插件化框架简化版
     */
    private void initPluginSimple() {
        //模拟下载APK:从资产文件复制到私有目录
        String apkName = "ToolPluggableDemo2.apk";
        HookTool.extractAssets(context, apkName);
        String apkPath = context.getFilesDir().getAbsolutePath() + "/" + apkName;

        HookManager.getInstance().hookStartActivity(context);
        HookManager.getInstance().hookHookMh(context);
        HookManager.getInstance().hookPackgeManager();
        HookManager.getInstance().putLoadedApk(apkPath);
        //插件化框架简化版不需要此步骤
        //HookManager.getInstance().injectPluginClass(apkPath);

        /**
         * 加载插件APK的资源
         */
        try {
            //将插件APK的资源添加到宿主中
            assetManager = AssetManager.class.newInstance();
            Method addAssetPathMethod = assetManager.getClass().getDeclaredMethod("addAssetPath", String.class);
            addAssetPathMethod.setAccessible(true);
            addAssetPathMethod.invoke(assetManager, apkPath);

            //创建字符串资源
            Method ensureStringBlocks = AssetManager.class.getDeclaredMethod("ensureStringBlocks");
            ensureStringBlocks.setAccessible(true);
            ensureStringBlocks.invoke(assetManager);

            //生成新的Resources：融合了插件和宿主的Resources
            Resources supResource = context.getResources();
            newResource = new Resources(assetManager, supResource.getDisplayMetrics(), supResource.getConfiguration());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 插件化框架简化版，指定插件的assetManager
     *
     * @return 融合了插件资源的assetManager
     */
    public void setAssetManager() {
        try {
            Method addAssetPathMethod = Application.class.getDeclaredMethod("setAssetManager", AssetManager.class);
            addAssetPathMethod.setAccessible(true);
            addAssetPathMethod.invoke(context, assetManager);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 插件化框架简化版，指定插件的Resources
     *
     * @return 融合了插件资源的Resources
     */
    public void setResources() {
        try {
            Method addAssetPathMethod = Application.class.getDeclaredMethod("setNewResource", Resources.class);
            addAssetPathMethod.setAccessible(true);
            addAssetPathMethod.invoke(context, newResource);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Context getContext() {
        return context;
    }
}
